package com.adcc.swingui.serialize;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.log4j.Logger;

/**
 * <p>
 * Title: SerializeObjectFactory
 * </p>
 * <p>
 * Description: 序列化对象工场
 * </p>
 * <p>
 * Copyright: Copyright (c) 2010
 * </p>
 * 
 * @author charlie
 * @version 1.0.0
 */
public class SerializeObjectFactory {
	/** 日志打印 */
	private static Logger log = Logger.getLogger(SerializeObjectFactory.class);
	/** 序列化对象存放 ，如果存在在内存中获取对象速度比较快*/
	private static Map<String, AbstractSeriObject> objtable = new ConcurrentHashMap<String, AbstractSeriObject>();
	private static String splitStr = "|||";
	/**
	 * 获取序列化对象  default目录
	 * @param className 类名称
	 * @return
	 * @throws Exception
	 */
	public static AbstractSeriObject getSerializeObject(String className) {
		return getSerializeObject(className, null);
	}

	/**
	 * 获取对象指定用户目录
	 * @param className 类名称
	 * @param dirName 用户目录
	 * @return
	 * @throws Exception
	 */
	public static AbstractSeriObject getSerializeObject(String className,
			String dirName) {
		if (dirName == null) {
			dirName = "default";
		}

		String key = dirName + splitStr + className;

		if (objtable.containsKey(key)) {
			return objtable.get(key);
		}

		AbstractSeriObject reobj = null;
		SerializeObjectParams.setSubDirectory(dirName);
		String savePath = System.getProperty("user.dir")
				+ SerializeObjectParams.getObjsavePath() + "/" + className
				+ SerializeObjectParams.getExtname();
		File file = new File(savePath);

		if (file.exists()) {
			log.debug("序列化工厂读取本地对象" + file.getAbsolutePath());
			ObjectInputStream is = null;
			try {
				is = new ObjectInputStream(new FileInputStream(savePath));
				reobj = (AbstractSeriObject) is.readObject();// 从流中读取数据
				is.close();
				is = null;
			} catch (Exception e) {
				log.error("对象反序列化失败" + savePath, e);
			} finally {
				if (is != null) {
					try {
						is.close();
					} catch (Exception e) {
						log.error("对象反序列化失败，流关闭异常" + savePath, e);
					}
				}
			}
		}
		if (reobj == null) {
			reobj = createNewInstance(className);
		}
		objtable.put(dirName + splitStr + className, reobj);
		return reobj;
	}

	/**
	 * 创建新对象
	 * @param className  类名称
	 * @return
	 */
	private static AbstractSeriObject createNewInstance(String className) {
		AbstractSeriObject o = null;
		try {
			Class c = Class.forName(className);
			Constructor con = c.getConstructor(new Class[] {});
			o = (AbstractSeriObject) con.newInstance();
		} catch (Exception e) {
			log.error("反射创建对象失败" + className, e);
		}
		return o;
	}

	/** 
	 * 保存单个序列化对象  default目录下
	 */
	public static void saveSerializeObject(String className) {
		saveSerializeObject(className, null);
	}
	/**
	 * 指定目录保存序列化对象
	 * @param className 类名
	 * @param dirName 目录名
	 * @throws Exception
	 */
	public static void saveSerializeObject(String className, String dirName) {

		if (dirName == null) {
			dirName = "default";
		}

		if (className != null) {
			String key = dirName + splitStr + className;
			AbstractSeriObject obj = null;
			if (objtable.containsKey(key)) {
				obj = objtable.get(key);
			} else {
				obj = createNewInstance(className);
			}
			saveSerializeObject(obj, dirName);
		}
	}

	/**
	 * 序列化对象
	 * @param obj 对象
	 * @param userName 用户名
	 * @throws Exception
	 */
	private static void saveSerializeObject(AbstractSeriObject obj,
			String userName) {
		if (!obj.takePropertyChange()) {
			// 如果属性没有被更改过
			return;
		}
		log.debug("开始保存对象:" + obj.getClass());
		ObjectOutputStream os = null;
		String savePath = null;

		try {
			// 创建目录
			SerializeObjectParams.setSubDirectory(userName);

			savePath = System.getProperty("user.dir")
					+ SerializeObjectParams.getObjsavePath() + "/"
					+ obj.getClass().getName()
					+ SerializeObjectParams.getExtname();
			os = new ObjectOutputStream(new FileOutputStream(savePath));
			os.writeObject(obj);// 将对象写进文件
			os.flush();
			os.close();
			os = null;
		} catch (Exception e) {
			log.error("对象序列化保存失败" + savePath, e);
		} finally {
			if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
					log.error("对象序列化保存失败,流关闭异常" + savePath, e);
				}
			}
		}
		
		try {
			for( ISerializeObjectSavedListener lis : obj.getListenerList() ) {
				lis.onPropertySaved( obj.getChangePropertyNames() ) ;
			}
		} catch (Exception e) {
			log.error("调用保存监听器失败" + savePath, e);
		}

		log.debug(obj.getClass() + " -> 保存成功, 保存路径：" + savePath);
	}

	/**
	 * 保存所有有过修改的对象
	 * 
	 * @throws Exception
	 */
	@Deprecated
	public static void saveAllSerializeObject() {
		for (String classpath : objtable.keySet()) {
			AbstractSeriObject obj = objtable.get(classpath);

			if (obj.takePropertyChange()) {
				String userDir = classpath.split(splitStr)[0];
				saveSerializeObject(obj, userDir);
			}
		}

		objtable.clear();
	}
	
}